package com.sojson.util.file.system.impl.minio;

import java.io.InputStream;

import com.sojson.constant.Constant;
import com.sojson.util.StringUtil;
import com.sojson.util.file.FileUtil;
import com.sojson.util.file.bean.UploadBean;
import com.sojson.util.file.system.FileSystemInterface;
import com.sojson.util.file.system.impl.minio.config.MinioConfig;
import com.sojson.util.id.IdUtil;

import io.minio.GetObjectArgs;
import io.minio.GetPresignedObjectUrlArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.RemoveObjectArgs;
import io.minio.http.Method;

/**
 * MiniO文件系统工具类
 *
 * @author liu
 * @Date 2020-06-15 14:45:43
 * @Description
 *
 */
public class MinioUtilImpl implements FileSystemInterface {

    private static MinioUtilImpl miniOUtilsImpl;
    private MinioClient client = new MinioConfig().minioClient();

    private MinioUtilImpl() {}

    /**
     * 文件上传
     *
     * @param filePath  文件位置
     * @param dir       上传目录
     * @return
     * @throws Exception
     */
    @Override
    public UploadBean upload(String filePath, String dir) throws Exception {
        InputStream inputStream = null;
        try {
            inputStream = FileUtil.readInputStream(filePath);
            return upload(inputStream, dir, FileUtil.getFileSuffix(filePath));
        } finally {
            FileUtil.closeStream(inputStream);
        }
    }

    /**
     * 文件上传
     *
     * @param fileStream    文件流
     * @param dir           上传目录
     * @param fileSuffix    文件后缀
     * @return
     * @throws Exception
     */
    @Override
    public UploadBean upload(InputStream fileStream, String dir, String fileSuffix) throws Exception {
        String objectName = new StringBuilder(dir).append(IdUtil.uuid()).append(fileSuffix).toString();

        client.putObject(PutObjectArgs.builder().bucket(BUCKET_NAME).object(objectName)
            .stream(fileStream, fileStream.available(), -1).build());

        UploadBean upload = new UploadBean();
        upload.setObjectName(objectName);
        return upload;
    }

    /**
     * 文件上传
     *
     * @param fileBytes     文件字节流
     * @param dir           上传目录
     * @param fileSuffix    文件后缀
     * @return
     * @throws Exception
     */
    @Override
    public UploadBean upload(byte[] fileBytes, String dir, String fileSuffix) throws Exception {
        InputStream inputStream = null;
        try {
            inputStream = FileUtil.readInputStream(fileBytes);
            return upload(inputStream, dir, fileSuffix);
        } finally {
            FileUtil.closeStream(inputStream);
        }
    }

    /**
     * 下载文件
     *
     * @param objectName    唯一标识
     * @param dir           文件路径
     * @param fileName      文件名
     * @return
     * @throws Exception
     */
    @Override
    public boolean download(String objectName, String dir, String fileName) throws Exception {
        InputStream inputStream = null;
        try {
            inputStream = downloadGetStream(objectName);
            FileUtil.write(inputStream,
                new StringBuilder(FileUtil.THIS_LOCALITY_DIRECTORY_BUCKET_NAME_BASE).append("/").append(dir).append("/")
                    .append(fileName).toString());
        } finally {
            FileUtil.closeStream(inputStream);
        }
        return true;
    }

    /**
     * 下载文件
     *
     * @param objectName    唯一标识
     * @return
     * @throws Exception
     */
    @Override
    public InputStream downloadGetStream(String objectName) throws Exception {
        return client.getObject(GetObjectArgs.builder().bucket(BUCKET_NAME).object(objectName).build());
    }

    /**
     * 下载文件
     *
     * @param objectName    唯一标识
     * @return
     * @throws Exception
     */
    @Override
    public byte[] downloadGetBytes(String objectName) throws Exception {
        InputStream inputStream = null;
        try {
            inputStream = downloadGetStream(objectName);
            return FileUtil.readByes(inputStream);
        } finally {
            FileUtil.closeStream(inputStream);
        }
    }

    /**
     * 删除文件
     *
     * @param objectName    唯一标识
     * @return
     * @throws Exception
     */
    @Override
    public boolean remove(String objectName) throws Exception {
        client.removeObject(RemoveObjectArgs.builder().bucket(BUCKET_NAME).object(objectName).build());
        return true;
    }

    /**
     * 获取文件路径
     *
     * @param objectName    唯一标识
     * @return
     * @throws Exception
     */
    @Override
    public String getUrl(String objectName) throws Exception {
        StringBuilder sb = new StringBuilder(MinioConfig.ENDPOINT);
        sb.append("/");
        sb.append(BUCKET_NAME);
        sb.append("/");
        sb.append(objectName);

        return StringUtil.encode(sb.toString(), Constant.UTF8);
    }

    /**
     * 获取文件路径(临时路径)
     *
     * @param objectName    唯一标识
     * @return
     * @throws Exception
     */
    @Override
    public String getUrlTemporary(String objectName) throws Exception {
        return getUrlTemporary(objectName, FILE_TIMEOUT);
    }

    /**
     * 获取文件路径(临时路径)
     *
     * @param objectName    唯一标识
     * @param timeout       超时时间(单位: 秒)
     * @return
     * @throws Exception
     */
    @Override
    public String getUrlTemporary(String objectName, int timeout) throws Exception {
        GetPresignedObjectUrlArgs objectArgs = GetPresignedObjectUrlArgs.builder().bucket(BUCKET_NAME)
            .object(objectName).expiry(timeout).method(Method.GET).build();
        return StringUtil.encode(client.getPresignedObjectUrl(objectArgs), Constant.UTF8);
    }

    public static MinioUtilImpl getInstances() {
        if (StringUtil.isBlankObject(miniOUtilsImpl)) {
            miniOUtilsImpl = new MinioUtilImpl();
        }
        return miniOUtilsImpl;
    }

}